#!/usr/bin/env node

/*
For a Meteor package that is exposed as both a global and an ES6 module, we
unfortunately need to provide two copies of the typings for compatibility with
existing code that expects to augment and use either the global or the ES6
module.  We maintain the module typings by hand and use this script to generate
the global typings in the `globals/` subdirectory.  Not every package is exposed
globally; `generate-globals` reads `tsconfig.json` to get the list of expected
files in `globals/`.  Similarly, we maintain `meteor-tests.ts` (which tests the
the modules that also have globals) by hand, and this script generates
`globals/meteor-tests.ts` (which tests the globals).

Usage: scripts/generate-globals

This script may be used by Meteor typings packages in DefinitelyTyped other than
`meteor` itself.

Inspired by prior art (but not believed to constitute a derivative work):
https://github.com/meteor-typings/meteor/blob/09ef92da99549ac090603ce70cfa632db4fad6e7/gulpfile.js#L43
*/

// @ts-check

// We are relying on the following modules to be transitive dependencies of
// DefinitelyTyped and npm 5 to install them in a place visible to us. :/
let ts = require("typescript");
let path = require("path");
let os = require("os");
let fs = require("fs");
let mkdirp = require("mkdirp");
let rimraf = require("rimraf");

function formatDiagnostic(diag) {
    return ts.flattenDiagnosticMessageText(diag.messageText, os.EOL);
}

let rcfResult = ts.readConfigFile("tsconfig.json", (path) => {
    try {
        return fs.readFileSync(path, "UTF-8");
    } catch (e) {
        return undefined;
    }
});
let configObject = rcfResult.config;
if (!configObject) {
    throw new Error(formatDiagnostic(rcfResult.error));
}
rimraf.sync("globals");
rimraf.sync("test/globals");
let readmeText = `This \`globals/\` directory is generated by \`scripts/generate-globals\`!  To update
this directory, edit the corresponding files outside \`globals/\` and re-run
\`scripts/generate-globals\`.`.replace("\n", os.EOL);
mkdirp.sync("globals");
fs.writeFileSync("globals/README.md", readmeText, "UTF-8");
mkdirp.sync("test/globals");
fs.writeFileSync("test/globals/README.md", readmeText, "UTF-8");
for (let outFile of configObject.files) {
    let m = /^(test\/)?globals\/(.*)$/.exec(outFile);
    if (m) {
        let inFile = (m[1] || "") + m[2];
        let inLines = fs.readFileSync(inFile, "UTF-8").split(/\r?\n/);
        let isTest = !!m[1];
        let outLines = inLines.map((l) => {
            if (/^import /.test(l)) return null;
            if (isTest) {
                return l;
            } else {
                let m2;
                // Capture any line with a comment
                if ((m2 = /^    (\/\/.*)$/.exec(l)) != null) return m2[1];
                
                if ((m2 = /^    ([^} ].*)$/.exec(l)) != null) return "declare " + m2[1];
                if ((m2 = /^    (.*)$/.exec(l)) != null) return m2[1];
                if (l == "") return l;
                return null;  // Strip `declare module "..." {` and `}`.
            }
        }).filter((l) => l != null);
        mkdirp.sync(path.dirname(outFile));
        fs.writeFileSync(outFile, outLines.join(os.EOL), "UTF-8");
    }
}
